<html>
	<body>
		<pre>
		public class DisposeSample
		{
			public bool disposed =false;
			public FileStream stream;
			string text;
			public DisposeSample(string fileName)
			{
				stream=new FileStream(fileName);
				string text="Hello";
			}
			public void Dispose()
			{
				Dispose(true);
				//告诉GC不需要执行~DisposeSample函数。
				GC.SuppressFinalize(this);
			}
			public void Dispose(bool disposeManageResource)
			{
				if(!disposed )
				{
					//释放非托管资源
					if(disposeManageResource)
					{
						text=null;
					}
					//释放托管资源
					stream.Dispose();
					disposed=true; 
				}
			}
			~DisposeSample()
			{
				//释放非托管资源
				//这个时候当前对象中的text已经被回收
				Dispose(false);
			}
		}
		为什么要加IDisposeable接口？
		每一个继承该接口的类，都会实现一个默认的析构函数
		~DisposeSample()
		{
			//释放非托管资源
			//这个时候当前对象中的text已经被回收
			Dispose(false);
		}
		
		
			网上大部分文章对Dispose的理解都是错的,因此对此要整理一下,防止内存泄露.

在C#中有一些类实现了IDispose()接口.
这个接口指的是释放一些系统资源,而非.net资源.任何.net资源均可由GC释放.
如果你使用的资源非常大,比如说图像处理,或者视频算法处理才有可能手动调用GC释放资源.否则请不要手动调用GC.

当然C#是面向对象的.有一些父类与子类,其中一部分子类需要释放系统资源,另一部分不需要释放系统资源,
但作为父类,一定要有IDispose接口,而不需要释放系统资源的子类因为继承的原因也会实现Dispose接口,
但实际上你不调用Dispose函数也不会存在内存泄露.
比如: HashAlgorithm类是哈希类,也是MD5CryptoServiceProvider类和MD5的父类,MD5CryptoServiceProvider需要调用Dispose,而MD5则不需要.

在windows中一般需要一个指针指向一个固定大小的内存块,比如窗口,按钮,文件等.指向该内存块的指针就被称为Handle,
如果Dispose中出现调用extern修饰的函数,或者出现Handle.Close(),就一定要手动调用Dispose函数.

.net 源码:
https://referencesource.microsoft.com/

分析:
ManualResetEvent:
 	[System.Security.SecuritySafeCritical]  // auto-generated
        protected virtual void Dispose(bool explicitDisposing)
        {
            if (safeWaitHandle != null)
            {
                safeWaitHandle.Close();
            }
        }
因为使用了safeWaitHandle 因此必须调用Dispose接口.有些人说GC也会回收,纯扯淡,GC回收分为三级,
如果内存需要占满或者到达一定时间才释放,那和内存泄露的结果都是一样的,GC执行时程序有可能会卡死1-2秒种.

	public void Dispose()
        {
            GC.SuppressFinalize(this);
        }
关于GC的用法,一般调用这种方法,是因为该类实例成员中存在大量的byte[]数组资源,在GC释放时会占有较多的时间,因此要提前释放,
防止GC自动回收时程序卡死.当然如果你使用的byte[]资源不多,也可以不用调用Dispose().
这就是为什么MemoryStream没有使用非托管内存却需要手动调用Dispose的原因.

结论:
ManualResetEvent, Semaphore, ReaderWriterLockSlim 都需要手动调用dispose或使用using语句
MemoryStream不需要调用Dispose()也不会引起内存泄露,但是如果占用内存较大,提前释放能减轻GC压力.
FileStream需要调用Dispose();
Image需要调用Dispose();
RSACryptoServiceProvider 需要调用Dispose() 新版的RSA.Create()不需要调用Dispose()
MD5CryptoServiceProvider 需要调用Dispose() 新版的MD5.Create()不需要调用Dispose()
SqlConnection必须要Dispose();
SqlCommand不需要Dispose();
SqlDataAdapter不需要Dispose();
HttpClient不需要Dispose();//虽然有非静态资源
SymmetricAlgorithm 不需要调用Dispose();
SymmetricAlgorithm 不需要调用Dispose();

如果有关于Dispose不明白的.QQ联系348764327.
		</pre>
	</body>
</html>